package net.zjitc.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import net.zjitc.model.domain.*;
import net.zjitc.model.vo.CountDataVO;
import net.zjitc.model.vo.CountLikeAndCommentVO;
import net.zjitc.model.vo.CountWeekVO;
import net.zjitc.model.vo.NewNumVO;
import net.zjitc.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
public class HomeServiceImpl implements HomeService {

    @Resource
    private UserService userService;

    @Resource
    private BlogService blogService;

    @Resource
    private BlogCommentsService blogCommentsService;

    @Resource
    private TeamService teamService;

    @Resource
    private BlogLikeService blogLikeService;



    @Override
    public NewNumVO count(LocalDate date) {
        NewNumVO newUserNumVO = new NewNumVO();

        Long dayNum = dayNum(date);
        newUserNumVO.setTodayNum(dayNum);
        Long yesterdayUser = dayNum(date.minusDays(1));
        newUserNumVO.setYesterdayNum(yesterdayUser);
        Long monthNum = monthNum(date,date.minusMonths(1));
        newUserNumVO.setMonthNum(monthNum);
        Long lastMonthNum = monthNum(date.minusMonths(1),date.minusMonths(2));
        newUserNumVO.setLastMonthNum(lastMonthNum);
        return newUserNumVO;
    }

    @Override
    public CountDataVO countData(LocalDate date) {
        LocalDateTime begin = LocalDateTime.of(date.minusMonths(1), LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        CountDataVO countDataVO = new CountDataVO();
        HashMap<String, Long> map = new HashMap<>();

        Long userNum = monthNum(date, date.minusMonths(1));
        countDataVO.setUserNum(userNum);
        map.put("新增用户", userNum);

        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        wrapper.gt(Blog::getCreateTime, begin).lt(Blog::getCreateTime, end);
        Long blogNum = blogService.count(wrapper);
        countDataVO.setBlogNum(blogNum);
        map.put("新增贴文", blogNum);

        LambdaQueryWrapper<BlogComments> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.gt(BlogComments::getCreateTime, begin).lt(BlogComments::getCreateTime, end);
        Long blogCommentsNum = blogCommentsService.count(wrapper1);
        countDataVO.setCommentNum(blogCommentsNum);
        map.put("新增评论", blogCommentsNum);

        LambdaQueryWrapper<Team> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.gt(Team::getCreateTime, begin).lt(Team::getCreateTime, end);
        Long teamNum = teamService.count(wrapper2);
        countDataVO.setTeamNum(teamNum);
        map.put("新增群聊", teamNum);

        return countDataVO;
    }

    @Override
    public CountWeekVO countWeek(LocalDate date) {
        List<LocalDate> dateList = new ArrayList<>();

        LocalDate beginDate = date.minusDays(7);
        while (!beginDate.equals(date)){
            beginDate = beginDate.plusDays(1);
            dateList.add(beginDate);
        }

        List<Long> blogCountList = new ArrayList<>();

        for (LocalDate localDate: dateList){
            LocalDateTime begin = LocalDateTime.of(localDate, LocalTime.MIN);
            LocalDateTime end = LocalDateTime.of(localDate, LocalTime.MAX);

            LambdaQueryWrapper<Blog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.gt(Blog::getCreateTime, begin).lt(Blog::getCreateTime, end);
            Long countBlog = blogService.count(lambdaQueryWrapper);
            blogCountList.add(countBlog);
        }

        return CountWeekVO
                .builder()
                .dateList(StringUtils.join(dateList, ","))
                .blogList(StringUtils.join(blogCountList, ","))
                .build();
    }

    @Override
    public CountLikeAndCommentVO countLikeAndComment(LocalDate date) {
        List<LocalDate> dateList = new ArrayList<>();

        LocalDate beginDate = date.minusDays(7);
        while (!beginDate.equals(date)){
            beginDate = beginDate.plusDays(1);
            dateList.add(beginDate);
        }
        List<Long> likeCount = new ArrayList<>();
        List<Long> commentCount = new ArrayList<>();

        for (LocalDate localDate: dateList){
            LocalDateTime begin = LocalDateTime.of(localDate, LocalTime.MIN);
            LocalDateTime end = LocalDateTime.of(localDate, LocalTime.MAX);

            LambdaQueryWrapper<BlogLike> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.gt(BlogLike::getCreateTime, begin).lt(BlogLike::getCreateTime, end);
            Long countBlogLike = blogLikeService.count(lambdaQueryWrapper);
            likeCount.add(countBlogLike);

            LambdaQueryWrapper<BlogComments> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            lambdaQueryWrapper1.gt(BlogComments::getCreateTime, begin).lt(BlogComments::getCreateTime, end);
            Long countBlogComment = blogCommentsService.count(lambdaQueryWrapper1);
            commentCount.add(countBlogComment);
        }


        return CountLikeAndCommentVO
                .builder()
                .dateList(StringUtils.join(dateList, ","))
                .likeList(StringUtils.join(likeCount, ","))
                .commentList(StringUtils.join(commentCount, ","))
                .build();
    }

    public Long dayNum(LocalDate date) {
        LocalDateTime begin = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.gt(User::getCreateTime, begin).lt(User::getCreateTime, end);
        return userService.count(lambdaQueryWrapper);
    }

    public Long monthNum(LocalDate date, LocalDate lastMonth){
        LocalDateTime endMonth = LocalDateTime.of(date, LocalTime.MAX);
        LocalDateTime beginMonth = LocalDateTime.of(lastMonth, LocalTime.MIN);
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.gt(User::getCreateTime, beginMonth).lt(User::getCreateTime, endMonth);
        return userService.count(lambdaQueryWrapper);
    }


}
